import { NotFound, BadRequest } from 'http-errors'
import { type InferAttributes, type WhereOptions } from 'sequelize'
import User from '@/database/models/user'
import Order from '@/database/models/order'
import { generateTradeNo } from '@/utils/tools'
import roleService from './roleService'

/** 查询订单列表 */
const getOrders = async (userId: number, query: Query) => {
  const pageNum = Math.abs(Number(query.pageNum)) || 1
  const pageSize = Math.abs(Number(query.pageSize)) || 10
  const offset = (pageNum - 1) * pageSize
  const where: WhereOptions<InferAttributes<Order>> = {
    userId,
  }
  if (query.outTradeNo) {
    where.outTradeNo = query.outTradeNo as string
  }
  if (query.tradeNo) {
    where.tradeNo = query.tradeNo as string
  }
  if (query.status) {
    where.status = query.status as string
  }
  const { rows, count } = await Order.findAndCountAll({
    ...getCondition(),
    where,
    order: [['id', 'DESC']],
    limit: pageSize,
    offset,
  })
  return {
    orders: rows,
    pagination: {
      total: count,
      pageNum,
      pageSize,
    },
  }
}

/** 查询订单详情 */
const getOrderInfo = async (userId: number, outTradeNo: string) => {
  const order = await getOrder(userId, outTradeNo)
  return { ...order.dataValues, id: undefined }
}

/** 创建订单 */
const addOrder = async (userId: number, body: Body) => {
  const { roleId } = body
  const outTradeNo = generateTradeNo()
  const role = await roleService.getRole(roleId)
  if (+role.price <= 0) {
    throw new BadRequest('免费角色无需付费。')
  }
  const order = await Order.create({
    outTradeNo,
    userId,
    roleId: role.id,
    subject: role.name,
    totalAmount: role.price,
    durationMonths: role.durationMonths,
    status: 0,
  })
  return order
}

/**
 * 公共方法：关联用户
 */
function getCondition() {
  return {
    attributes: { exclude: ['id', 'UserId'] },
    include: [
      {
        model: User,
        as: 'user',
        attributes: ['id', 'username', 'avatar'],
      },
    ],
  }
}

/**
 * 公共方法：查询当前订单
 */
async function getOrder(userId: number, outTradeNo: string, judgeStatus: boolean = false) {
  if (!outTradeNo) {
    throw new BadRequest(`订单号不能为空。`)
  }
  const order = await Order.findOne({
    ...getCondition(),
    attributes: { exclude: ['UserId'] },
    where: { userId, outTradeNo },
  })
  if (!order) {
    throw new NotFound(`订单号: ${outTradeNo} 的订单未找到。`)
  }
  if (judgeStatus && order.status !== 0) {
    throw new BadRequest(`订单${order.status === 1 ? '已支付' : '已取消'}。`)
  }
  return order
}

export default {
  getOrders,
  getOrderInfo,
  addOrder,
  getOrder,
}
